<?php

/**
 * @method config @return Modules_Users_Config
 */
class Modules_Users extends Module {

	public $name = 'users';
	public $title = "Пользователи сайта";

	public static function subMenu () {
		return array(
			array(
				'icon' => '/tpl/admin/images/list.png',
				'url' => '/admin.php?module=users&action=role',
				'title' => 'Роли',
			),
			array(
				'icon' => '/tpl/admin/images/users.png',
				'url' => '/admin.php?module=users&action=group',
				'title' => 'Группы',
			),
			array(
				'icon' => '/tpl/admin/images/user.png',
				'url' => '/admin.php?module=users&action=user',
				'title' => 'Пользователи',
			),
			array(
				'icon' => '/tpl/admin/images/users_data.png',
				'url' => '/admin.php?module=users&action=users_properties',
				'title' => 'Данные пользователей',
			),
			array(
				'icon' => '/tpl/admin/images/users_data.png',
				'url' => '/admin.php?module=users&action=prp',
				'title' => '',
			),
		);
	}

	public function actions () {
		return array(
			'login_form' => "Форма авторизации/информация о пользователе/меню пользователя",
		);
	}

	public function mainActions () {
		return array(
			'user' => "Страница текущего пользователя",
			'login_form' => "Форма авторизации/информация о пользователе/меню пользователя",
		);
	}

	protected function _actionproperties (Blocks $block) {
		switch ($block->action) {
			default:
				return "Нет";
				break;
		}
	}

	public function adminActionIndex () {
		Request::redirect('admin.php?module=users&action=user');
	}

	public function adminActionRole () {
		$this->access("r");

		$roles = RolesTable::getInstance()->findAll();
		$this->tpl()->assign(array(
			'roles' => $roles,
		));
		return $this->tpl()->fetch('role_list.html');
	}

	public function adminActionRole_create () {
		$this->access("c");

		$role = new Roles();

		return $this->_role_edit($role, 'role_create.html');
	}

	public function adminActionRole_edit () {
		$this->access("c");

		$id = (int) $_REQUEST['id'];
		if (!$id) Request::redirect(404);
		$role = RolesTable::getInstance()->find($id);
		if (!$role) Request::redirect(404);

		return $this->_role_edit($role, 'role_create.html');
	}

	public function adminActionRole_delete () {
		$this->access("d");

		$id = (int) $_REQUEST['id'];
		if (!$id) Request::redirect(404);
		$role = RolesTable::getInstance()->find($id);
		if (!$role) Request::redirect(404);

		$role->delete();

		Request::redirect('admin.php?module=users&action=role');
	}

	public function adminActionRole_save () {
		$this->access("c");

		$roleData = isset($_REQUEST['role']) ? $_REQUEST['role'] : array();
		$rmData = isset($_REQUEST['roles_modules']) ? $_REQUEST['roles_modules'] : array();

		$roleData['id'] = (int) $roleData['id'];

		$modules = ModulesTable::getInstance()->findByDql('`name` != "null"');
		$role = $roleData['id'] ? RolesTable::getInstance()->find($roleData['id']) : new Roles();
		$role->fromArray($roleData);
		$role->save();

		if ($roleData['id']) {
			$q = Doctrine_Query::create()->delete('RolesModules r')->where('r.role_id = ' . $role->id);
			$q->execute();
		}

		$q = new Doctrine_Collection('RolesModules');
		foreach ($modules as $module) {
			$module_id = $module->id;

			$record = new RolesModules();
			$record->role_id = $role->id;
			$record->module_id = $module->id;

			$record->r = (isset($rmData[$module_id]['r']) && $rmData[$module_id]['r'] == 1 ? 1 : 0);
			$record->c = (isset($rmData[$module_id]['c']) && $rmData[$module_id]['c'] == 1 ? 1 : 0);
			$record->p = (isset($rmData[$module_id]['p']) && $rmData[$module_id]['p'] == 1 ? 1 : 0);
			$record->d = (isset($rmData[$module_id]['d']) && $rmData[$module_id]['d'] == 1 ? 1 : 0);

			$q->add($record);
		}

		$q->save();

		Request::redirect(empty($_REQUEST['apply']) ? "?module=users&action=role" : "?module=users&action=role_edit&id={$role->id}");
	}

	public function adminActionGroup () {
		$this->access("r");

		$groups = GroupsTable::getInstance()->findAll();
		$this->tpl()->assign(array(
			'groups' => $groups,
		));
		return $this->tpl()->fetch('group_list.html');
	}

	public function adminActionGroup_create () {
		$this->access("c");

		$group = new Groups();

		return $this->_group_edit($group, 'group_create.html');
	}

	public function adminActionGroup_edit () {
		$this->access("c");

		$id = (int) $_REQUEST['id'];
		if (!$id) Request::redirect(404);

		$group = GroupsTable::getInstance()->find($id);
		if (!$group) Request::redirect(404);

		return $this->_group_edit($group, 'group_create.html');
	}

	public function adminActionGroup_save () {
		$this->access("c");

		$groupData = isset($_REQUEST['group']) ? $_REQUEST['group'] : array();
		$roles = isset($_REQUEST['roles']) ? $_REQUEST['roles'] : array();

		$groupData['id'] = (int) $groupData['id'];

		$group = !empty($groupData['id']) ? GroupsTable::getInstance()->find($groupData['id']) : new Groups();
		$group->fromArray($groupData);
		$group->save();

		//if (!$group->save()) return $this->_group_edit($group, 'group_create.html');

		if ($groupData['id']) $row = Doctrine_Query::create()->delete()->from('RolesGroups')->where('group_id = ?', array($group->id))->execute();

		$q = new Doctrine_Collection("RolesGroups");
		foreach ($roles as $id => $value) {
			if ($value == 1) {
				$id = (int) $id;

				$record = new RolesGroups();
				$record->role_id = $id;
				$record->group_id = $group->id;

				$q->add($record);
			}
		}

		$q->save();

		Request::redirect(empty($_REQUEST['apply']) ? "?module=users&action=group" : "?module=users&action=group_edit&id={$group->id}");
	}

	public function adminActionUser () {
		$this->access("r");

		$users = Doctrine_Query::create()
				->from("Users u")
				->leftJoin("u.Groups")
				->execute();
		$this->tpl()->assign(array(
			'users' => $users
		));
		return $this->tpl()->fetch('user_list.html');
	}

	public function adminActionUser_create () {
		$this->access("c");

		$user = new Users();
		$user->date_register = time();
		$tpl = 'user_create.html';
		return $this->_user_edit($user, $tpl);
	}

	public function adminActionUser_edit () {
		$this->access("c");

		$id = (int) $_REQUEST['id'];
		if (!$id) Request::redirect(404);
		$user = UsersTable::getInstance()->find($id);
		if (!$user) Request::redirect(404);

		$tpl = 'user_create.html';
		return $this->_user_edit($user, $tpl);
	}

	public function adminActionUser_active () {
		$this->access("p");

		$id = (int) $_REQUEST['id'];
		if (!$id) Request::redirect(404);
		$user = UsersTable::getInstance()->find($id);
		if (!$user) Request::redirect(404);

		$user->active = 1;
		$user->save();

		Request::redirect("?module=users&action=user");
	}

	public function adminActionUser_unactive () {
		$this->access("p");

		$id = (int) $_REQUEST['id'];
		if (!$id) Request::redirect(404);
		$user = UsersTable::getInstance()->find($id);
		if (!$user) Request::redirect(404);

		$user->active = 0;
		$user->save();

		Request::redirect("?module=users&action=user");
	}

	public function adminActionUser_delete () {
		$this->access("d");

		$id = (int) $_REQUEST['id'];
		if (!$id) Request::redirect(404);
		$user = UsersTable::getInstance()->find($id);
		if (!$user) Request::redirect(404);

		$user->delete();

		Request::redirect("?module=users&action=user");
	}

	public function adminActionUser_save () {
		$this->access("c");

		$userData = isset($_REQUEST['user']) ? $_REQUEST['user'] : array();

		$userData['id'] = (int) $userData['id'];

		$userData['password'] = trim($userData['password']);
		if (empty($userData['password'])) unset($userData['password']);

		$userData['date_register'] = strtotime($userData['date_register']);
		$userData['date_lastactive'] = !empty($userData['date_lastactive']) ? strtotime($userData['date_register']) : null;

		$user = !$userData['id'] ? new Users() : UsersTable::getInstance()->find($userData['id']);
		$user->fromArray($userData);
		$user->save();

		if ($userData['id']) Doctrine_Query::create()->delete()->from('UsersGroups')->where('user_id = ?', array($user->id))->execute();

		if (count($userData['_groups'])) {
			$q = new Doctrine_Collection("UsersGroups");
			foreach ($userData['_groups'] as $group_id) {
				$record = new UsersGroups();
				$record->group_id = $group_id;
				$record->user_id = $user->id;
				$q->add($record);
			}

			$q->save();
		}

		Request::redirect(empty($_REQUEST['apply']) ? "?module=users&action=user" : "?module=users&action=user_edit&id={$user->id}");
	}

	public function adminActionUsers_properties () {
		$this->access("r");

		$properties = Doctrine_Query::create()
				->from("UsersProperties p")
				->execute();
		$_property = new UsersProperties();

		self::$mainTitle = "Данные о пользователе";

		return $this->renderTpl('users_properties.html', array(
			"properties" => $properties,
			"_property" => $_property
		));
	}

	public function adminActionProperty_save () {
		$this->access("c");

		$propData = isset($_REQUEST['property']) ? $_REQUEST['property'] : array();
		$property = isset($propData['id']) && $propData['id'] ? UsersPropertiesTable::getInstance()->find($propData['id']) : new UsersProperties();

		unset($propData['id']);
		$propData['required'] = isset($propData['required']) ? (int) $propData['required'] : 0;

		$property->fromArray($propData);
		$property->save();

		Request::redirect(-1);
	}

	public function adminActionProp_delete () {
		$this->access("d");

		$property = isset($_REQUEST['id']) ? (int) $_REQUEST['id'] : 0;
		if (!$property) Request::redirect(404);

		$property = Doctrine_Query::create()
				->from("UsersProperties p")
				->where('p.id = ?', $property)
				->fetchOne();
		$rows = $property->delete();

		if (App::$XMLHttpRequest) return $rows;

		Request::redirect(-1);
	}

	public function adminActionData_edit () {
		$this->access("c");

		$id = isset($_REQUEST['id']) ? (int) $_REQUEST['id'] : 0;
		if (!$id) Request::redirect(404);

		$user = Doctrine_Query::create()
				->from("Users u")
				->leftJoin('u.UserData d')
				->leftJoin('d.Property')
				->where('u.id = ?', $id)
				->fetchOne();
		if (!$user) Request::redirect(404);

		$properties = Doctrine_Query::create()
				->from("UsersProperties")
				->execute();

		self::$mainTitle = "Редактировать данные пользователя: {$user->login}";

		return $this->renderTpl('data_edit.html', array(
			'user' => $user,
			'properties' => $properties
		));
	}

	public function adminActionData_save () {
		$this->access("c");

		$data = isset($_REQUEST['user']) ? $_REQUEST['user'] : array();
		$data['id'] = (int) $data['id'];

		$delRows = Doctrine_Query::create()
				->delete('UsersData d')
				->where('d.user_id = ?', $data['id'])
				->execute();
		$user = UsersTable::getInstance()->find($data['id']);
		if (!$user) Request::redirect(404);

		$userData = $data['UserData'];
		unset($data['id']);
		unset($data['UserData']);

		$i = 0;
		$errors = array();
		foreach ($userData as $property_id => $value) {
			$property = UsersPropertiesTable::getInstance()->find($property_id);
			if (!$property) Request::redirect(404);

			$value = $property->prepare($value);
			if ($property->required == 1 && empty($value)) $errors[] = "Property \"{$property->name}\" can`t be empty.";

			$validate = $property->_validate($value);
			if ($validate !== true) $errors[] = $validate;

			$data['UserData'][$i]['property_id'] = $property_id;
			$data['UserData'][$i]['value'] = $value;
			$i++;
		}
		$user->fromArray($data);

		if (count($errors)) {
			$properties = Doctrine_Query::create()
					->from("UsersProperties")
					->execute();

			self::$mainTitle = "Редактировать данные пользователя: {$user->login}";

			return $this->renderTpl('data_edit.html', array(
				'user' => $user,
				'properties' => $properties,
				'errors' => $errors
			));
		}

		$user->save();

		Request::redirect('?module=users&action=user');
	}

	public function actionLogin_form () {
		$block = $this->block;

		$user = UserAccess::user();

		if (!$user) {
			$user = new Users();
			return $this->renderTpl('login_form.html', array(
				'user' => $user,
				'url' => $block->LinkedPage->url,
			));
		} else {
			return $this->renderTpl('login_menu.html', array(
				'user' => $user,
				'block' => $block,
			));
		}
	}

	public function actionLogin () {
		$loginData = $_REQUEST['login'];

		if (UserAccess::user()) Request::redirect($_SERVER['HTTP_REFERER']);

		$_REQUEST['login']['password'] = UserAccess::hash($_REQUEST['login']['password']);

		$user = UserAccess::loadInSession($_REQUEST['login']);

		if (!$user) {
			$error = 'Неверный логин/пароль. Попробуйте еще раз';
			$user = new Users();
		} else if (!$user->active) {
			$error = "Ваша учетная запись заблокированна администрацией, либо вы еще не активировали её.";
		} else {

			if (UserAccess::$first_time) {
				Request::redirect(Request::cUrl(array('action' => 'profile_edit', 'first_time' => 1)));
			} else {
				Request::redirect($_SERVER['HTTP_REFERER']);
			}
		}

		$this->tpl()->assign(array(
			'url' => $this->block->LinkedPage->url,
			'user' => $user,
			'error' => $error,
		));
		$tpl = $this->getTpl('login_fail.html');
		return $this->tpl()->fetch($tpl);
	}

	public function actionUser () {
		if (Request::isset_('app') && !Request::empty_('app')) {
			$block = new Blocks();
			$block->Property[1]['property'] = "user";
			$block->Property[1]['value'] = UserAccess::user()->id;
			$blogs = new Modules_Blogs('user_blogs');
			return $blogs->actionUser_blogs();
		}

		$this->tpl()->assign(array(
			'user' => UserAccess::user(),
		));
		return $this->tpl()->fetch($this->getTpl('user.html'));
	}

	public function actionRegister () {
		$error = null;
		if (isset($_POST['register'])) {
			$data = $_POST['user'];

			if ($data['password'] != $data['repassword']) {
				$error = "Passwords do not match";
				$user = new Users();
			} else {
				$data['Groups'] = $this->config()->get('default_group');

				$user = new Users();
				$user->fromArray($data);
				$user->date_register = time();

				if (!$user->isValid()) {
					$error = $user->getErrorStackAsString();
				} else {
					$user->save();
					$this->_sendConfirmMail($user);
				}
			}
		} else {
			$user = new Users();
		}

		return $this->renderTpl('register.html', array(
			'url' => $this->block->LinkedPage->url,
			'error' => $error,
			'user' => $user,
		));
	}

	public function actionConfirm_mail () {
		$key = Request::get('key');
		$user = Doctrine_Query::create()
				->from('Users u')
				->where('u.confirm_mail_key = ?', $key)
				->fetchOne();
		if (!$user) Request::redirect(404);

		$user->confirm_mail_key = null;
		$user->active = 1;
		$user->save();

		return "Ваша учетная запись активирована. Теперь вы можете войти на сайт используя свои данные.";
	}

	public function actionProfile_edit () {
		$user = UserAccess::user();
		if (!$user) return "Вы должны быть зарегистриованы и авторизованы, чтобы иметь возможность редактировать свои данные";

		$first_time = Request::get('first_time');
		$properties = Doctrine_Query::create()
				->from("UsersProperties")
				->execute();

		return $this->renderTpl('profile_edit.html', array(
			'first_time' => $first_time,
			'user' => $user,
			'properties' => $properties,
		));
	}
	
	public function actionProfile_save(){
		$data = isset($_REQUEST['user']) ? $_REQUEST['user'] : array();
		$data['id'] = (int) $data['id'];
		
		$user = UserAccess::user();
		if(!$user || $user->id != $data['id']) return "Вы должны быть зарегистриованы и авторизованы, чтобы иметь возможность редактировать свои данные";

		$delRows = Doctrine_Query::create()
				->delete('UsersData d')
				->where('d.user_id = ?', $data['id'])
				->execute();

		$userData = $data['UserData'];
		unset($data['id']);
		unset($data['UserData']);

		$i = 0;
		$errors = array();
		foreach ($userData as $property_id => $value) {
			$property = UsersPropertiesTable::getInstance()->find($property_id);
			if (!$property) Request::redirect(404);

			$value = $property->prepare($value);
			if ($property->required == 1 && empty($value)) $errors[] = "Property \"{$property->name}\" can`t be empty.";

			$validate = $property->_validate($value);
			if ($validate !== true) $errors[] = $validate;

			$data['UserData'][$i]['property_id'] = $property_id;
			$data['UserData'][$i]['value'] = $value;
			$i++;
		}

		if (count($errors)) {
			$properties = Doctrine_Query::create()
					->from("UsersProperties")
					->execute();

			self::$mainTitle = "Редактировать данные пользователя: {$user->login}";

			return $this->renderTpl('data_edit.html', array(
				'user' => $user,
				'properties' => $properties,
				'errors' => $errors
			));
		} else {
			$user->fromArray($data);
			$user->save();
			Request::redirect(-1);
		}
	}

	private function _sendConfirmMail ($user) {
		$mail = new Mail();
		$mail->to = $user->email;
		$mail->from = App::getInstance()->config()->get('admin_mail');
		$mail->subject = "Проверка почтового ящика";
		$mail->html = true;
		$mail->body = "Чтобы подтвердить регистрацию на сайте, жмакнтие на <a href=\"" . Request::url($this->block->LinkedPage->link, array('action' => 'confirm_mail', 'key' => $this->_getConfirmKey($user)), true) . "\">ссылку</a><br/>
			Ссылка будет доступна в течении 24 часов";

		$tpl = new Templater(App::getInstance()->page->Template->templateDir);
		$tpl->assign(array(
			'user' => $user,
			'subject' => $mail->subject,
			'body' => $mail->body,
		));

		$mail->body = $tpl->fetch('mail.html');
		$mail->send();
	}

	private function _getConfirmKey ($user) {
		$str = $this->_generateConfirmKey($user);
		$user->confirm_mail_key = $str;
		$user->save();
		return $str;
	}

	private function _generateConfirmKey ($user) {
		return md5($user->id . session_id() . $_SERVER['REMOTE_ADDR'] . time());
	}

	private function _user_edit ($user, $tpl) {
		$groups = GroupsTable::getInstance()->findAll();

		App::registerCoreScript('jquery');
		App::registerCoreScript('jquery-ui');
		App::registerCoreScript('base');
		App::registerCoreStyle('jquery-ui');

		$this->tpl()->assign(array(
			'user' => $user,
			'groups' => $groups,
		));

		return $this->tpl()->fetch($tpl);
	}

	private function _group_edit ($group, $tpl) {
		$roles = RolesTable::getInstance()->findAll();

		$this->tpl()->assign(array(
			'group' => $group,
			'roles' => $roles,
		));

		return $this->tpl()->fetch($tpl);
	}

	private function _role_edit ($role, $tpl) {
		$modules = ModulesTable::getInstance()->findByDql('`name` != "null"');

		App::registerCoreScript('jquery');
		App::registerScript('/js/base_edit.js');

		$this->tpl()->assign(array(
			'role' => $role,
			'modules' => $modules,
		));

		return $this->tpl()->fetch($tpl);
	}

}